package com.caoustc.okhttplib.okhttp

import android.os.AsyncTask
import com.caoustc.okhttplib.okhttp.callback.FileDownloadCallback
import com.caoustc.okhttplib.utils.FileUtils
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream

class FileDownloadTask(private val url: String, target: File, callback: FileDownloadCallback?) :
    AsyncTask<Void?, Long?, Boolean>() {
    private val okHttpClient: OkHttpClient?
    private val callback: FileDownloadCallback?
    private val target: File
    private var previousTime: Long = 0
    override fun onPreExecute() {
        super.onPreExecute()
        previousTime = System.currentTimeMillis()
        callback?.onStart()
    }

    override fun doInBackground(vararg params: Void?): Boolean {
        val request = Request.Builder()
            .url(url)
            .build()
        var suc = false
        try {
            val response = okHttpClient?.newCall(request)?.execute()
            val total = response?.body()!!.contentLength()
            saveFile(response)
            if (total == target.length()) {
                suc = true
            }
        } catch (e: Exception) {
            e.printStackTrace()
            suc = false
        }
        return suc
    }

    override fun onProgressUpdate(vararg values: Long?) {
        super.onProgressUpdate(*values)
        if (callback != null && values != null && values.size >= 2) {
            val sum = values[0]
            val total = values[1]
            val progress = (sum!! * 100.0f / total!!).toInt()
            var totalTime = (System.currentTimeMillis() - previousTime) / 1000
            if (totalTime == 0L) {
                totalTime += 1
            }
            val networkSpeed = sum / totalTime
            callback.onProgress(progress, networkSpeed)
        }
    }

    override fun onPostExecute(suc: Boolean) {
        super.onPostExecute(suc)
        if (suc) {
            callback?.onDone()
        } else {
            callback?.onFailure()
        }
    }

    @Throws(IOException::class)
    fun saveFile(response: Response): String {
        var `is`: InputStream? = null
        val buf = ByteArray(2048)
        var len = 0
        var fos: FileOutputStream? = null
        return try {
            `is` = response.body()!!.byteStream()
            val total = response.body()!!.contentLength()
            var sum: Long = 0
            FileUtils.Companion.makeFolders(target.parentFile)
            fos = FileOutputStream(target)
            while (`is`.read(buf).also { len = it } != -1) {
                sum += len.toLong()
                fos.write(buf, 0, len)
                if (callback != null) {
                    publishProgress(sum, total)
                }
            }
            fos.flush()
            target.absolutePath
        } finally {
            try {
                `is`?.close()
            } catch (e: IOException) {
            }
            try {
                fos?.close()
            } catch (e: IOException) {
            }
        }
    }

    init {
        okHttpClient = OkHttpManager.instance?.okHttpClientBuilder?.build()
        this.callback = callback
        this.target = target
        FileUtils.Companion.makeFolders(target.parentFile)
        if (target.exists()) {
            target.delete()
        }
    }
}